#pragma once

#include "MockerInterface.h"
#include "FunctionCallRecord.h"

namespace MockItNow
{
	template<typename R, typename A1>
	struct FreeFunctionRecorder1
	{
		static R RecordMockedFunction(A1 argument1)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(1, 0);
			record->RecordArgument<A1>(argument1);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1>
	struct FreeFunctionRecorder1<void, A1>
	{
		static void RecordMockedFunction(A1 argument1)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(1, 0);
			record->RecordArgument<A1>(argument1);
		}
	};

	template<typename R>
	struct FreeFunctionRecorder1<R, void>
	{
		static R RecordMockedFunction()
		{
			MockerInterface::Instance().RegisterRecordFunctionCall(0, 0);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<>
	struct FreeFunctionRecorder1<void, void>
	{
		static void RecordMockedFunction()
		{
			MockerInterface::Instance().RegisterRecordFunctionCall(0, 0);
		}
	};

	template<typename R, typename A1, typename A2>
	struct FreeFunctionRecorder2
	{
		static R RecordMockedFunction(A1 argument1, A2 argument2)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(2, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2>
	struct FreeFunctionRecorder2<void, A1, A2>
	{
		static void RecordMockedFunction(A1 argument1, A2 argument2)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(2, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
		}
	};

	template<typename R, typename A1, typename A2, typename A3>
	struct FreeFunctionRecorder3
	{
		static R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(3, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3>
	struct FreeFunctionRecorder3<void, A1, A2, A3>
	{
		static void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(3, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4>
	struct FreeFunctionRecorder4
	{
		static R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(4, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4>
	struct FreeFunctionRecorder4<void, A1, A2, A3, A4>
	{
		static void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(4, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
	struct FreeFunctionRecorder5
	{
		static R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(5, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4, typename A5>
	struct FreeFunctionRecorder5<void, A1, A2, A3, A4, A5>
	{
		static void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(5, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
	struct FreeFunctionRecorder6
	{
		static R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(6, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
	struct FreeFunctionRecorder6<void, A1, A2, A3, A4, A5, A6>
	{
		static void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(6, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
	struct FreeFunctionRecorder7
	{
		static R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(7, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
	struct FreeFunctionRecorder7<void, A1, A2, A3, A4, A5, A6, A7>
	{
		static void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(7, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
	struct FreeFunctionRecorder8
	{
		static R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7, A8 argument8)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(8, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
			record->RecordArgument<A8>(argument8);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
	struct FreeFunctionRecorder8<void, A1, A2, A3, A4, A5, A6, A7, A8>
	{
		static void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7, A8 argument8)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(8, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
			record->RecordArgument<A8>(argument8);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
	struct FreeFunctionRecorder9
	{
		static R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7, A8 argument8, A9 argument9)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(9, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
			record->RecordArgument<A8>(argument8);
			record->RecordArgument<A9>(argument9);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
	struct FreeFunctionRecorder9<void, A1, A2, A3, A4, A5, A6, A7, A8, A9>
	{
		static void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7, A8 argument8, A8 argument9)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(9, 0);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
			record->RecordArgument<A8>(argument8);
			record->RecordArgument<A9>(argument9);
		}
	};

	template<typename R, typename A1>
	struct MemberFunctionRecorder1
	{
		R RecordMockedFunction(A1 argument1)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(1, this);
			record->RecordArgument<A1>(argument1);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1>
	struct MemberFunctionRecorder1<void, A1>
	{
		void RecordMockedFunction(A1 argument1)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(1, this);
			record->RecordArgument<A1>(argument1);
		}
	};

	template<typename R>
	struct MemberFunctionRecorder1<R, void>
	{
		R RecordMockedFunction()
		{
			MockerInterface::Instance().RegisterRecordFunctionCall(0, this);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<>
	struct MemberFunctionRecorder1<void, void>
	{
		void RecordMockedFunction()
		{
			MockerInterface::Instance().RegisterRecordFunctionCall(0, this);
		}
	};

	template<typename R, typename A1, typename A2>
	struct MemberFunctionRecorder2
	{
		R RecordMockedFunction(A1 argument1, A2 argument2)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(2, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2>
	struct MemberFunctionRecorder2<void, A1, A2>
	{
		void RecordMockedFunction(A1 argument1, A2 argument2)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(2, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
		}
	};

	template<typename R, typename A1, typename A2, typename A3>
	struct MemberFunctionRecorder3
	{
		R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(3, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3>
	struct MemberFunctionRecorder3<void, A1, A2, A3>
	{
		void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(3, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4>
	struct MemberFunctionRecorder4
	{
		R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(4, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4>
	struct MemberFunctionRecorder4<void, A1, A2, A3, A4>
	{
		void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(4, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
	struct MemberFunctionRecorder5
	{
		R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(5, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4, typename A5>
	struct MemberFunctionRecorder5<void, A1, A2, A3, A4, A5>
	{
		void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(5, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
	struct MemberFunctionRecorder6
	{
		R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(6, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
	struct MemberFunctionRecorder6<void, A1, A2, A3, A4, A5, A6>
	{
		void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(6, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
	struct MemberFunctionRecorder7
	{
		R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(7, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
	struct MemberFunctionRecorder7<void, A1, A2, A3, A4, A5, A6, A7>
	{
		void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(7, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
	struct MemberFunctionRecorder8
	{
		R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7, A8 argument8)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(8, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
			record->RecordArgument<A8>(argument8);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
	struct MemberFunctionRecorder8<void, A1, A2, A3, A4, A5, A6, A7, A8>
	{
		void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7, A8 argument8)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(8, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
			record->RecordArgument<A8>(argument8);
		}
	};

	template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
	struct MemberFunctionRecorder9
	{
		R RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7, A8 argument8, A9 argument9)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(9, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
			record->RecordArgument<A8>(argument8);
			record->RecordArgument<A9>(argument9);
			static typename TypeInfo<R>::StorageType r;
			return r;
		}
	};

	template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
	struct MemberFunctionRecorder9<void, A1, A2, A3, A4, A5, A6, A7, A8, A9>
	{
		void RecordMockedFunction(A1 argument1, A2 argument2, A3 argument3, A4 argument4, A5 argument5, A6 argument6, A7 argument7, A8 argument8, A9 argument9)
		{
			FunctionCallRecord* record = MockerInterface::Instance().RegisterRecordFunctionCall(9, this);
			record->RecordArgument<A1>(argument1);
			record->RecordArgument<A2>(argument2);
			record->RecordArgument<A3>(argument3);
			record->RecordArgument<A4>(argument4);
			record->RecordArgument<A5>(argument5);
			record->RecordArgument<A6>(argument6);
			record->RecordArgument<A7>(argument7);
			record->RecordArgument<A8>(argument8);
			record->RecordArgument<A9>(argument9);
		}
	};
}
